﻿using System.Collections.Generic;
using System.Linq;
using ARMIR.util;
using RimWorld;
using UnityEngine;
using Verse;
using Verse.Sound;
using static UnityEngine.GraphicsBuffer;

namespace ARMIR {
    /// <summary>
    /// 使用如你所愿的hediff，拥有该hediff的角色会周期性的对范围内的敌人造成伤害，同时角色本身意识锁定到31%
    /// </summary>
    public class HediffComp_AsYourWish : HediffComp {
        private int ticksToNextLock;
        private int lenBlock; //初始长度
        private int waveTimes; //波次次数
        private int boomTimes; //爆破计数
        private bool isLocking; //是否在锁定中
        private bool isClearing; //是否在结算中
        private bool isBooming; //是否在爆破中
        private List<IntVec3> resonanceTM03 = new List<IntVec3>(); //共振03战术装备列表
        private List<IntVec3> scanPosition = new List<IntVec3>(); //环坐标列表
        private List<IntVec3> finalLockedPosition = new List<IntVec3>(); //最终决定被锁定的坐标
        private int explosivePace; //逐个爆破进度
        //TD特效
        private int linePace; //逐个渲染进度
        private float lineGrowPace; //单线条渲染进度
        private float lineGrowthRate = 0.8f; //线段渲染增长速度
        private float cirRadiusStatic = 3f; //渲染环的基础半径
        private float cirRadiusOffset = 2.5f; //渲染环的可能半径偏差
        private float cirGrowthRate = 0.8f; //渲染环的增长速度 
        private List<float> cirRadius = new List<float>(); //每个渲染环的半径
        private List<float> cirRadiusPace = new List<float>(); //每个渲染环的进度
        //释放中特效
        private int gapEffecter; //效果间隔
        private bool firstGet; //第一次施放音效

        public HediffCompProperties_AsYourWish Props => (HediffCompProperties_AsYourWish)props;

        public override void CompPostMake() {
            base.CompPostMake();
            ticksToNextLock = Props.tickInterval;
            isLocking = true;
            isClearing = false;
            isBooming = false;
            firstGet = false;
            waveTimes = 0;
            boomTimes = 0;
            gapEffecter = 15;
        }

        public override void CompPostTick(ref float severityAdjustment) {
            base.CompPostTick(ref severityAdjustment);

            // 只在pawn存活且在地图上时生效
            if (Pawn.Dead || Pawn.Map == null) return;
            //角色倒下时无法施放
            if (Pawn.Downed) {
                parent.pawn.health.RemoveHediff(parent);
            }

            // 索敌倒计时
            ticksToNextLock--;
            if (ticksToNextLock <= 0) {
                //TryTriggerExplosion();
                TryLockWithWave();
                ticksToNextLock = Props.tickInterval;
            }
            // TD特效
            TriggerTDEffecter();
            // effecter特效
            if (gapEffecter > 0) { 
                gapEffecter--;
                if (gapEffecter <= 0) {
                    gapEffecter = 15;
                    TryTriggerEffecter();
                }
            }
            if (!firstGet) { 
                firstGet = true;
                TryTriggerSound();
            }
        }
        //按波次边缘搜索敌人，随后结算打击。
        private void TryLockWithWave() {
            // 是否处于结算状态
            if (isClearing) {
                //处于结算状态，但结算是否读条结束
                if (waveTimes > Props.gapClearing) {
                    //读条结束
                    if (!isBooming) {
                        //结算状态，存储所有带有标记且依旧处于范围内的敌人
                        finalLockedPosition.Clear();
                        //获得地图上敌对于技能使用者的单位为list enemies
                        var enemies = Pawn.Map.mapPawns.AllPawnsSpawned.Where(p => p.HostileTo(Pawn) && !p.Downed).ToList();
                        //将enemies中处于使用者范围内或者共振范围内的enemy加入最终锁定爆破列表finalLocked
                        if (enemies != null) {
                            foreach (var enemy in enemies) {
                                if (enemy.Position.DistanceTo(Pawn.Position) <= Props.radius && enemy.health.hediffSet.HasHediff(Props.lockHediff)) {
                                    //且该坐标距离其它被锁定坐标至少有两个爆炸范围距离
                                    if (finalLockedPosition.Any()) {
                                        bool allowIn = true;
                                        foreach (var existedPosition in finalLockedPosition) {
                                            if (enemy.Position.DistanceTo(existedPosition) <= Props.explosionRadius * 1f) {
                                                allowIn = false;
                                                break;
                                            }
                                        }
                                        if (allowIn) {
                                            finalLockedPosition.AddUnique(enemy.Position);
                                        }
                                    }
                                    else {
                                        finalLockedPosition.AddUnique(enemy.Position);
                                    }
                                    continue;
                                }
                                if (resonanceTM03 != null) {
                                    foreach (var resonanceDot in resonanceTM03) {
                                        if (enemy.Position.DistanceTo(resonanceDot) <= Props.TMradius && enemy.health.hediffSet.HasHediff(Props.lockHediff)) {
                                            if (finalLockedPosition.Any()) {
                                                bool allowIn = true;
                                                foreach (var existedPosition in finalLockedPosition) { 
                                                    if (enemy.Position.DistanceTo(existedPosition) <= Props.explosionRadius * 1f) {
                                                        allowIn = false;
                                                        break;
                                                    }
                                                }
                                                if (allowIn) {
                                                    finalLockedPosition.AddUnique(enemy.Position);
                                                }
                                            }else {
                                                finalLockedPosition.AddUnique(enemy.Position);
                                            }
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                        //进入爆破状态
                        boomTimes = -50; //为了适应特效进度，第一次爆炸间隔延长
                        isBooming = true;
                        explosivePace = 0;
                        linePace = 0;
                        cirRadius.Clear();
                        cirRadiusPace.Clear();
                    } else if (boomTimes > Props.gapBooming) { //爆破状态读条完成
                        //是否还有剩余需要爆破的敌人
                        if (explosivePace < finalLockedPosition.Count) {
                            //取需要被爆破的敌人中第一个
                            IntVec3 explosionPosition = finalLockedPosition[explosivePace];
                            //特效
                            TickUtil DelayTick = Current.Game.GetComponent<TickUtil>();
                            //射出特效
                            speDraw.DragLight(parent.pawn.Map, parent.pawn.Position.ToVector3(), 10, 0.15f, 10, false, true, 0,0.3f);
                            if (DelayTick != null) {
                                DelayTick.TickTimeManager(5, () => {
                                    //射入特效
                                    speDraw.DragLight(parent.pawn.Map, explosionPosition.ToVector3(), 10, 0.25f, 30, true, false, 5,0.8f);
                                }, true);
                                DelayTick.TickTimeManager(15, () => {
                                    EffecterDef HitIn = DefDatabase<EffecterDef>.GetNamed("ARMIR_AsYourWish_EffecterB"); //命中特效
                                    HitIn.Spawn(explosionPosition, Pawn.Map);

                                    List<Thing> ExplosiveIgnoredPawns = new List<Thing>();
                                    ExplosiveIgnoredPawns = parent.pawn.Map.mapPawns.AllPawnsSpawned.Where(p => p.Faction == Faction.OfPlayer && p.Position.DistanceTo(explosionPosition) < Props.radius + 2).OfType<Thing>().ToList();
                                    ExplosiveIgnoredPawns.AddRange(parent.pawn.Map.listerThings.ThingsMatching(ThingRequest.ForGroup(ThingRequestGroup.HaulableEver)).Where(p => p.Position.DistanceTo(explosionPosition) < Props.radius + 2));
                                    ExplosiveIgnoredPawns.AddRange(parent.pawn.Map.listerThings.ThingsMatching(ThingRequest.ForGroup(ThingRequestGroup.Corpse)).Where(p => p.Position.DistanceTo(explosionPosition) < Props.radius + 2));
                                    ExplosiveIgnoredPawns.Add(parent.pawn);

                                    int powerBase = (int)ARMIR_ModSettings.powerSet;
                                    //生成爆炸(小范围高伤害高穿甲)
                                    GenExplosion.DoExplosion(
                                        center: explosionPosition,
                                        map: Pawn.Map,
                                        radius: 1.5f,
                                        DamageDefOf.Cut,
                                        instigator: Pawn,
                                        damAmount: Props.damageAmount * powerBase,
                                        armorPenetration: 1.2f * powerBase,
                                        explosionSound: DefDatabase<SoundDef>.GetNamed("ARMIR_AsYourWishHitSound"),
                                        ignoredThings: ExplosiveIgnoredPawns
                                    );
                                    //余震
                                    GenExplosion.DoExplosion(
                                        center: explosionPosition,
                                        map: Pawn.Map,
                                        radius: Props.explosionRadius,
                                        DamageDefOf.Crush,
                                        instigator: Pawn,
                                        damAmount: Props.damageAmount / 2 * powerBase,
                                        armorPenetration: 0.4f * powerBase,
                                        explosionSound: DefDatabase<SoundDef>.GetNamed("ARMIR_AsYourWishHitSound"),
                                        ignoredThings: ExplosiveIgnoredPawns
                                    );
                                }, true);
                            }
                            //进度+1
                            explosivePace++;
                            //重置爆破读条
                            boomTimes = 0;
                        } else { //爆破结束
                            //如果非玩家阵营，则第一轮爆破结束后就停止技能
                            if (parent.pawn.Faction != Faction.OfPlayer) {
                                parent.pawn.health.RemoveHediff(parent);//移除hediff以停止技能
                            }
                            //重置
                            waveTimes = 0;
                            boomTimes = 0;
                            isClearing = false;
                            isLocking = false;
                            isBooming = false;
                            resonanceTM03.Clear();
                            explosivePace = 0;

                            //负面效果
                            bool hasEquipment = parent.pawn != null &&
                            (parent.pawn.equipment.AllEquipmentListForReading.Any(e =>
                            e.def == DefDatabase<ThingDef>.GetNamed("ARMIR_FPAMindMixer")) ||
                            parent.pawn.apparel.WornApparel.Any(a => a.def == DefDatabase<ThingDef>.GetNamed("ARMIR_FPAMindMixer")));
                            if (hasEquipment)
                            {
                                parent.pawn.needs.mood.thoughts.memories.TryGainMemory(DefDatabase<ThoughtDef>.GetNamed("ARMIR_MindLoad_weak")); //技能施放的思维负担
                            }
                            else
                            {
                                parent.pawn.needs.mood.thoughts.memories.TryGainMemory(DefDatabase<ThoughtDef>.GetNamed("ARMIR_MindLoad")); //技能施放的思维负担
                            }
                        }
                    } else {
                        //爆破状态读条未完成，读条进度++
                        boomTimes++;
                    }
                }else {
                    //结算读条未结束，读条进度++
                    waveTimes++;
                }
            }else { 
                //不处于结算状态，但是否处于索敌状态
                if (isLocking) {
                    //处于索敌状态
                    lenBlock++; //范围++
                    IntVec3 oriDot = Pawn.Position; //以hediff拥有者为中心
                    scanPosition.Clear();
                    //获得能力使用者为中心的边缘坐标列表
                    if (lenBlock <= Props.radius) {
                        int blockX = -lenBlock; int blockY = -lenBlock; //从左下角开始
                        scanPosition.AddUnique(new IntVec3(oriDot.x + -lenBlock, 0, oriDot.z + lenBlock));
                        for (int i = 0; i < 4;) {
                        if (i == 0) { scanPosition.AddUnique(new IntVec3(oriDot.x + blockX, 0,oriDot.z + blockY)); blockY++;
                            if (blockY == lenBlock) { i++; } }
                        if (i == 1) { blockX++; scanPosition.AddUnique(new IntVec3(oriDot.x + blockX, 0,oriDot.z + blockY));
                            if (blockX == lenBlock) { i++; } }
                        if (i == 2) { blockY--; scanPosition.AddUnique(new IntVec3(oriDot.x + blockX, 0,oriDot.z + blockY));
                            if (blockY == -lenBlock) { i++; } }
                        if (i == 3) { blockX--; scanPosition.AddUnique(new IntVec3(oriDot.x + blockX, 0,oriDot.z + blockY));
                            if (blockX == -lenBlock) { i++; } }
                        }
                    }
                    //获得共振03为中心的边缘坐标列表
                    if (resonanceTM03 != null) {
                        for (int x = 0; x < resonanceTM03.Count; x++) {
                            var resonanceDot = resonanceTM03[x];
                            if (resonanceDot.y <= Props.TMradius) { 
                                int resonanceLen = resonanceDot.y;
                                resonanceLen++;
                                int resonanceX = -resonanceLen; int resonanceZ = -resonanceLen;
                                scanPosition.AddUnique(new IntVec3(resonanceDot.x + -resonanceLen, 0, resonanceDot.z + resonanceLen));
                                for (int i = 0; i < 4;) {
                                if (i == 0) { scanPosition.AddUnique(new IntVec3(resonanceDot.x + resonanceX, 0,resonanceDot.z + resonanceZ)); resonanceZ++;
                                    if (resonanceZ == resonanceLen) { i++; } }
                                if (i == 1) { resonanceX++; scanPosition.AddUnique(new IntVec3(resonanceDot.x + resonanceX, 0,resonanceDot.z + resonanceZ));
                                    if (resonanceX == resonanceLen) { i++; } }
                                if (i == 2) { resonanceZ--; scanPosition.AddUnique(new IntVec3(resonanceDot.x + resonanceX, 0,resonanceDot.z + resonanceZ));
                                    if (resonanceZ == -resonanceLen) { i++; } }
                                if (i == 3) { resonanceX--; scanPosition.AddUnique(new IntVec3(resonanceDot.x + resonanceX, 0,resonanceDot.z + resonanceZ));
                                    if (resonanceX == -resonanceLen) { i++; } }
                                }
                                //增加这个03装置的共振范围
                                resonanceTM03[x] = new IntVec3(resonanceTM03[x].x, resonanceLen, resonanceTM03[x].z);
                            }
                        }
                    }

                    //对得到的坐标逐个执行效果
                    foreach (IntVec3 position in scanPosition) {
                        //特效
                        EffecterDef lockWaveBlock = DefDatabase<EffecterDef>.GetNamed("ARMIR_AsYourWish_EffecterD"); //单元地块特效
                        lockWaveBlock.Spawn(position, Pawn.Map); //在列表中得到的坐标生成效果
                        //对坐标附近的敌人进行标记
                        var enemies = Pawn.Map.mapPawns.AllPawnsSpawned.Where(p => p.HostileTo(Pawn) && p.Position.DistanceTo(position) <= 1).ToList();
                        foreach (Pawn enemie in enemies) {
                            if (!enemie.health.hediffSet.HasHediff(Props.lockHediff)) {
                                Hediff lockPawnHediff = HediffMaker.MakeHediff(Props.lockHediff, enemie);
                                enemie.health.AddHediff(lockPawnHediff);
                            }
                        }
                        //对坐标附近的03战术装备加入列表
                        ThingDef TMzeroThree = DefDatabase<ThingDef>.GetNamed("ARMIR_TMZeroThree_building"); //获得03战术装备的ThingDef
                        List<Thing> allTM03CloseToPosition = Pawn.Map.listerThings.ThingsOfDef(TMzeroThree).Where(x => x.Position.DistanceTo(position) <= 2).ToList(); //将所有距离该位置小于2的战术装备列入待选列表
                        //allTM03CloseToPosition = Pawn.Map.listerThings.ThingsInGroup(ThingRequestGroup.BuildingArtificial).Where(thing => thing.def.defName == "ARMIR_TMZeroThree_building" && thing.Position.DistanceTo(position) <= 2).ToList();
                        //Log.Message(allTM03CloseToPosition.Count);
                        //将附近的03战术装备中，位置x，z不重复在共振列表中的战术装备加入共振列表
                        if (allTM03CloseToPosition != null) { 
                            foreach (var TM03CTP in allTM03CloseToPosition) {
                                bool inSameXandZ = true;
                                if (resonanceTM03 != null) {
                                    foreach (var XZposition in resonanceTM03) { 
                                        if (!(TM03CTP.Position.x != XZposition.x && TM03CTP.Position.z != XZposition.z)) { 
                                            inSameXandZ = false; 
                                        }
                                    }
                                }
                                if (inSameXandZ) { 
                                    resonanceTM03.Add(new IntVec3(TM03CTP.Position.x, 0, TM03CTP.Position.z)); 
                                }
                            }
                        }
                    }
                    //是否索敌到最大范围
                    bool resonanceFinish = true;
                    if (resonanceTM03 != null) {
                        foreach (var resonanceLen in resonanceTM03) {
                            if (resonanceLen.y <= Props.TMradius) { 
                                resonanceFinish = false;
                            }
                        }
                    }
                    if (lenBlock > Props.radius && resonanceFinish) {
                        waveTimes = 0;
                        isClearing = true;
                    }
                }
                else {
                    //不处于索敌状态，但索敌是否读条结束
                    if (waveTimes > Props.gapWave) {
                        //读条结束，进入索敌状态
                        lenBlock = 0;
                        scanPosition.Clear();
                        isLocking = true;
                    }else { 
                        //读条未结束，读条进度++
                        waveTimes++;
                    }
                }
            }
            
        }
        //生成索敌者TD特效这一块//注释这一块
        private void TriggerTDEffecter() {
            if (isBooming) {
                float altitude = AltitudeLayer.MetaOverlays.AltitudeFor(); //显示层级这一块
                Material whiteMat = SolidColorMaterials.SimpleSolidColorMaterial(new Color(1f, 1f, 1f, 1f));
                //渲染渐进线段这一块
                if (finalLockedPosition.Any() && linePace + 1 <= finalLockedPosition.Count) {
                    //线段进度++这一块
                    lineGrowPace += lineGrowthRate;
                    //线性插值计算线段位置距离Linear Interpolation这一块
                    Vector3 A;
                    Vector3 B;
                    if (linePace == 0) { //从技能释放者开始链接这一块
                        A = new Vector3(Pawn.Position.x, altitude, Pawn.Position.z);
                        B = new Vector3(finalLockedPosition[linePace].x, altitude, finalLockedPosition[linePace].z);
                    }
                    else {
                        A = new Vector3(finalLockedPosition[linePace - 1].x, altitude, finalLockedPosition[linePace - 1].z);
                        B = new Vector3(finalLockedPosition[linePace].x, altitude, finalLockedPosition[linePace].z);
                    }
                    Vector3 direction = B - A;
                    float distance = direction.magnitude;
                    Vector2 U = new Vector2((B.x - A.x) / distance,(B.z - A.z) / distance);
                    Vector3 C = new Vector3(A.x + lineGrowPace * U.x, 0, A.z + lineGrowPace * U.y);
                    //绘制进度线
                    GenDraw.DrawLineBetween(A, C, whiteMat, 0.3f);
                    //GenDraw.DrawLineBetween(A.ToVector3(), finalLockedPosition[linePace].ToVector3(), whiteMat, 1f);
                    //诺距离抵达超出AB距离，进度+1这一块
                    if (lineGrowPace >= A.ToIntVec3().DistanceTo(B.ToIntVec3())) {
                        //设置该点的圆半径这一块
                        cirRadius.Add(cirRadiusStatic + Random.Range(-cirRadiusOffset, cirRadiusOffset));
                        cirRadiusPace.Add(0);
                        lineGrowPace = 0;
                        linePace++;
                    }
                }
                //已连接线段持续渲染
                if (finalLockedPosition.Any()) { 
                    for (int i = 0; i < finalLockedPosition.Count; i++) {
                        if (i == 0 && linePace > i) {
                            Vector3 lineStart = new Vector3(Pawn.Position.x, altitude, Pawn.Position.z);
                            Vector3 lineEnd = new Vector3(finalLockedPosition[i].x, altitude, finalLockedPosition[i].z);
                            GenDraw.DrawLineBetween(lineStart, lineEnd, whiteMat, 0.3f);
                        }else if (linePace > i) {
                            ARMIR_Draw.DrawWhiteHollowBlock(finalLockedPosition[i].ToVector3(), 0.4f, 0.4f, false, 0.4f); //测试方框这一块
                            Vector3 lineStart = new Vector3(finalLockedPosition[i].x, altitude, finalLockedPosition[i].z);
                            Vector3 lineEnd = new Vector3(finalLockedPosition[i - 1].x, altitude, finalLockedPosition[i - 1].z);
                            GenDraw.DrawLineBetween(lineStart, lineEnd, whiteMat, 0.3f);
                        }
                    }
                }
                //渲染环这一块
                if (cirRadius.Any()) {
                    for (int i = 0; i < cirRadius.Count; i++) {
                        //环抵达设定值之前不断增长这一块
                        if (cirRadiusPace[i] < cirRadius[i]) {
                            cirRadiusPace[i] = cirRadiusPace[i] + cirGrowthRate;
                        }
                        if (i >= explosivePace) { //诺环进度尚未被爆破则显示这一块
                            GenDraw.DrawCircleOutline(finalLockedPosition[i].ToVector3(), cirRadiusPace[i], whiteMat);
                        }
                    }
                }
            }
        }
        //直接对范围内的敌人产生爆炸
        private void TryTriggerExplosion() {

            // 1. 寻找范围内敌人
            var enemies = Pawn.Map.mapPawns.AllPawnsSpawned
                .Where(p => p.HostileTo(Pawn) &&
                            p.Position.DistanceTo(Pawn.Position) <= Props.radius)
                .ToList();
            if (enemies.Count == 0) return;

            // 2. 随机选择目标
            var target = enemies.RandomElement();

            

            // 3. 创建爆炸
            GenExplosion.DoExplosion(
                center: target.Position,
                map: Pawn.Map,
                radius: Props.explosionRadius,
                DamageDefOf.Crush,
                instigator: Pawn,
                damAmount: Props.damageAmount,
                armorPenetration: -1f,
                explosionSound: null,
                ignoredThings: new List<Thing> { Pawn }
            );
        }

        private void TryTriggerEffecter() {
            EffecterDef Effecter = DefDatabase<EffecterDef>.GetNamed("ARMIR_AsYourWish_EffecterC");
            Effecter.SpawnAttached(parent.pawn, parent.pawn.Map);
        }
        private void TryTriggerSound() {
            SoundDef.Named("ARMIR_asYourWishStartSound").PlayOneShot(new TargetInfo(parent.pawn.Position, parent.pawn.Map));
        }
    }
}